package com.duobaoyu.dby.supply.biz.strategy.message.order.logistics;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.duobaoyu.dby.channel.adapter.bean.message.order.OrderMessage;
import com.duobaoyu.dby.channel.adapter.enums.BizMessageTypeEnum;
import com.duobaoyu.dby.channel.adapter.enums.ChannelCodeEnum;
import com.duobaoyu.dby.channel.adapter.enums.biz.order.OrderStatusEnum;
import com.duobaoyu.dby.channel.boundary.bean.order.param.LogisticQueryParam;
import com.duobaoyu.dby.channel.boundary.bean.order.result.LogisticQueryResult;
import com.duobaoyu.dby.channel.boundary.template.SupplyChannelTemplate;
import com.duobaoyu.dby.common.core.constant.CommonConstants;
import com.duobaoyu.dby.common.mybatis.config.IdGeneratorSnowflake;
import com.duobaoyu.dby.supply.biz.constant.OperateSourceConstants;
import com.duobaoyu.dby.supply.biz.constant.OrderOperateConstants;
import com.duobaoyu.dby.supply.biz.enums.OrderParentTypeEnum;
import com.duobaoyu.dby.supply.biz.producer.SupplyChainMQProducer;
import com.duobaoyu.dby.supply.biz.service.order.OrderService;
import com.duobaoyu.dby.supply.biz.strategy.message.order.base.BaseOrderAsyncHandler;
import com.duobaoyu.dby.supply.common.biz.bo.message.ChannelMessageBO;
import com.duobaoyu.dby.supply.db.entity.order.Order;
import com.duobaoyu.dby.supply.db.entity.order.OrderConsignee;
import com.duobaoyu.dby.supply.db.entity.order.OrderLogistics;
import com.duobaoyu.dby.supply.db.entity.order.OrderProduct;
import com.duobaoyu.dby.supply.db.repository.order.OrderConsigneeRepository;
import com.duobaoyu.dby.supply.db.repository.order.OrderLogisticsRepository;
import com.duobaoyu.dby.supply.db.repository.order.OrderProductRepository;
import com.duobaoyu.dby.supply.db.repository.order.OrderRepository;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 物流消息同步
 *
 * @author fengshaoyu
 * @version 1.0.0
 * @date 2023/10/21 10:43
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class LogisticsSplitOrderInfoAsyncHandler extends BaseOrderAsyncHandler {

	private final OrderService orderService;
	private final OrderRepository orderRepository;
	private final TransactionTemplate transactionTemplate;
	private final IdGeneratorSnowflake idGeneratorSnowflake;
	private final SupplyChannelTemplate supplyChannelTemplate;
	private final SupplyChainMQProducer supplyChainMQProducer;
	private final OrderProductRepository orderProductRepository;
	private final OrderConsigneeRepository orderConsigneeRepository;
	private final OrderLogisticsRepository orderLogisticsRepository;

	@Override
	protected Set<String> channelCodes() {
		return Sets.newHashSet(ChannelCodeEnum.ZKH.getValue(),
				ChannelCodeEnum.ORIGINAL_LIFE.getValue());
	}

	@Override
	protected Set<Integer> bizMessageTypes() {
		return Sets.newHashSet(BizMessageTypeEnum.LOGISTICS_STATUS_CHANGE.getValue());
	}

	@Override
	protected Boolean executeHandler(ChannelMessageBO channelMessage, Object beforeResult) {
		List<OrderMessage> orderMessages = this.getMessage(channelMessage);
		List<Order> orderList = this.getOrderList(channelMessage);
		orderList = orderList.stream().filter(item -> Objects.equals(item.getChannelTradeOrderSn(),item.getChannelOrderSn())).collect(Collectors.toList());
		if(CollectionUtils.isEmpty(orderList)){
			log.info("message:{},channelCode:{},data:{}","物流回调失败",channelMessage.getChannelCode(),JSON.toJSONString(channelMessage));
			return Boolean.FALSE;
		}
		for (OrderMessage orderMessage : orderMessages) {
			List<OrderProduct> orderProductNewList = new ArrayList<>();
			Order order = orderList.stream().filter(item -> StringUtils.isNotBlank(orderMessage.getChannelOrderSn()) && StringUtils.isNotBlank(item.getChannelOrderSn()) ? Objects.equals(orderMessage.getChannelOrderSn(),item.getChannelOrderSn()) : Boolean.TRUE).findFirst().orElse(null);
			if (ObjectUtils.isEmpty(order)) {
				return Boolean.FALSE;
			}
			//当前订单地址信息
			OrderConsignee orderConsignee = orderConsigneeRepository.getOne(Wrappers.<OrderConsignee>lambdaQuery().eq(OrderConsignee::getOrderSn, order.getOrderSn()));
			//当前商品信息
			List<OrderProduct> orderProductList = orderProductRepository.list(Wrappers.<OrderProduct>lambdaQuery().eq(OrderProduct::getOrderSn, order.getOrderSn()));

			LogisticQueryParam logisticQueryParam = LogisticQueryParam.builder()
					.channelCode(order.getChannelCode())
					.orderTradeSn(order.getOrderTradeSn())
					.channelOrderSn(orderMessage.getPackageId())
					.build();

			List<LogisticQueryResult> logisticResultList;
			try {
				logisticResultList = supplyChannelTemplate.queryLogisticInfoList(Collections.singletonList(logisticQueryParam));
			}catch (Exception e){
				log.warn("message:{},data:{}","物流拆单未获取物流信息", JSON.toJSONString(channelMessage),e);
				return Boolean.FALSE;
			}

			LogisticQueryResult logisticResult = logisticResultList.stream().findFirst().orElse(null);
			if(Objects.isNull(logisticResult)){
				return Boolean.FALSE;
			}

			for (LogisticQueryResult.DeliveryGoodsInfo deliveryGoodsInfo : logisticResult.getDeliveryGoodsInfoList()) {
				Iterator<OrderProduct> iterator = orderProductList.iterator();
				while (iterator.hasNext()) {
					OrderProduct orderProduct = iterator.next();
					if (Objects.equals(orderProduct.getChannelSkuCode(),deliveryGoodsInfo.getChannelSkuCode())) {
						if (orderProduct.getSkuNum() - deliveryGoodsInfo.getSkuNum() == CommonConstants.ZERO) {
							orderProductNewList.add(orderProduct);
							iterator.remove();
						} else {
							Integer skuNum = orderProduct.getSkuNum() - deliveryGoodsInfo.getSkuNum();
							OrderProduct clone = orderProduct.clone();
							orderProduct.setSkuNum(skuNum);
							clone.setSkuNum(deliveryGoodsInfo.getSkuNum());
							orderProductNewList.add(clone);
						}
					}
				}
			}

			transactionTemplate.execute(new TransactionCallbackWithoutResult() {
				@Override
				protected void doInTransactionWithoutResult(@NotNull TransactionStatus transactionStatus) {
					orderRepository.update(Wrappers.<Order>lambdaUpdate().set(Order::getParentType, OrderParentTypeEnum.BEFORE_SPLIT.getValue())
							.eq(Order::getId, order.getId()));
					if (CollectionUtils.isNotEmpty(orderProductList)) {
						reckon(orderProductList);

						Order orderOne = createOrder(order.clone(), orderProductList);

						orderProductList.forEach(item -> item.setOrderSn(orderOne.getOrderSn()));
						orderRepository.save(orderOne);
						orderProductRepository.saveBatch(orderProductList);

						orderConsignee.setId(idGeneratorSnowflake.snowflakeId());
						orderConsignee.setOrderSn(orderOne.getOrderSn());
						orderConsigneeRepository.save(orderConsignee);
					}

					reckon(orderProductNewList);

					Order clone = order.clone();
					clone.setChannelOrderParentSn(order.getChannelTradeOrderSn());
					clone.setChannelOrderSn(orderMessage.getPackageId());
					clone.setOrderStatus(OrderStatusEnum.SHIPPED.getValue());
					Order orderTwo = createOrder(clone, orderProductNewList);

					orderProductNewList.forEach(item -> item.setOrderSn(orderTwo.getOrderSn()));
					orderRepository.save(orderTwo);
					orderProductRepository.saveBatch(orderProductNewList);

					orderConsignee.setId(idGeneratorSnowflake.snowflakeId());
					orderConsignee.setOrderSn(orderTwo.getOrderSn());
					orderConsigneeRepository.save(orderConsignee);


					List<OrderLogistics> orderLogisticsList = Lists.newArrayList();
					for (LogisticQueryResult.DeliveryInfo deliveryInfo:logisticResult.getDeliveryInfoList()) {
						OrderLogistics orderLogistics = new OrderLogistics();
						orderLogistics.setOrderSn(orderTwo.getOrderSn());
						orderLogistics.setPackageId(orderMessage.getPackageId());
						orderLogistics.setDeliveryOrderSn(deliveryInfo.getDeliveryOrderSn());
						orderLogistics.setDeliveryCarrier(deliveryInfo.getDeliveryCarrier());
						orderLogisticsList.add(orderLogistics);
					}

					orderLogisticsRepository.saveBatch(orderLogisticsList);

					OrderStatusEnum orderSubStatusOld = OrderStatusEnum.getOrderSubStatusEnum(orderTwo.getOrderStatus());
					OrderStatusEnum orderSubStatusNew = OrderStatusEnum.getOrderSubStatusEnum(orderMessage.getOrderStatus());
					orderService.updateStatusByOrderSnList(Collections.singletonList(orderTwo.getOrderSn()), orderSubStatusNew, orderSubStatusOld, OperateSourceConstants.OPERATION_CHANNEL, OrderOperateConstants.CHANNEL_PART_SEND,null);
				}
			});
			supplyChainMQProducer.orderAlterSend(order.getSupplyTradeSn(), order.getServerName());
			//售后处理
			this.afterSaleHandle(order);
		}
		return Boolean.TRUE;
	}
}
